﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml;
using CML.Services.Implementations;
using CML.Data;
using CML.Data.Instructions;

namespace Cml.UnitTests.Services
{
	[TestClass]
	public class InstructionServiceTests
	{
		[TestMethod]
		public void Test_AddXml()
		{
			try
			{
				var xmlService = new XmlService();
				var s = new InstructionService(xmlService);
				var doc = new XmlDocument();
				doc.LoadXml(@"
<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test"">
   <s:endPoints>
     <endPoint url=""http://test1"" />
   </s:endPoints>
</ns:xml>
");
				//to
				s.Add(doc, new AddXmlInstruction(
					@"<endPoint url=""http://test2"" />",
					"/ns:xml/s:endPoints",
					null
					)
				);
				Assert.AreEqual(@"<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test""><s:endPoints><endPoint url=""http://test1"" /><endPoint url=""http://test2"" /></s:endPoints></ns:xml>", doc.OuterXml);

				//before
				s.Add(doc, new AddXmlInstruction(
							@"<endPoint url=""http://test3"" />",
							"/ns:xml/s:endPoints/endPoint[@url='http://test1']",
							AddXmlInstruction.Locations.before
							)
						);
				Assert.AreEqual(@"<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test""><s:endPoints><endPoint url=""http://test3"" /><endPoint url=""http://test1"" /><endPoint url=""http://test2"" /></s:endPoints></ns:xml>", doc.OuterXml);

				//after
				s.Add(doc, new AddXmlInstruction(
							@"<endPoint url=""http://test4"" />",
							"/ns:xml/s:endPoints/endPoint[@url='http://test3']",
							AddXmlInstruction.Locations.after
							)
						);
				Assert.AreEqual(@"<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test""><s:endPoints><endPoint url=""http://test3"" /><endPoint url=""http://test4"" /><endPoint url=""http://test1"" /><endPoint url=""http://test2"" /></s:endPoints></ns:xml>", doc.OuterXml);
				
			}
			catch(Exception x)
			{
				var m = x.Message;
			}
		}

		[TestMethod]
		public void Test_UpdateXml()
		{
			
			var xmlService = new XmlService();
			var s = new InstructionService(xmlService);
			var doc = new XmlDocument();
			doc.LoadXml(@"
<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test"">
   <s:settings>
     <add key=""mykey"" value=""myvalue"" />
   </s:settings>
</ns:xml>
");
			s.Update(doc, new UpdateXmlInstruction("/ns:xml/s:settings/add[@key='mykey']/@value","newvalue"));
			Assert.AreEqual(@"<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test""><s:settings><add key=""mykey"" value=""newvalue"" /></s:settings></ns:xml>", doc.OuterXml);
			 
		}

		[TestMethod]
		public void Test_DeleteXml()
		{
			var xmlService = new XmlService();
			var s = new InstructionService(xmlService);
			var doc = new XmlDocument();
			doc.LoadXml(@"
<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test"">
   <s:settings>
     <add key=""mykey"" value = ""myvalue"" />
   </s:settings>
</ns:xml>
");
			s.Delete(doc, new DeleteXmlInstruction("/ns:xml/s:settings/add[@key='mykey']"));
			Assert.AreEqual(@"<ns:xml xmlns:ns=""http://cml.test"" xmlns:s=""http://settings.cml.test""><s:settings></s:settings></ns:xml>", doc.OuterXml);
		}

		[TestMethod]
		public void Test_CombinedXml()
		{
			try
			{
				var xmlService = new XmlService();
				var s = new InstructionService(xmlService);
				var doc = new XmlDocument();
				doc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<configuration>
</configuration>
");
				s.Add(doc, new AddXmlInstruction(
							@"<settings><add key=""first"" value=""1"" /></settings>",
							"/configuration",
							AddXmlInstruction.Locations.to
							)
						);
				s.Add(doc, new AddXmlInstruction(
							@"<add key=""last"" value=""3"" />",
							"//settings/add[@key='first']",
							AddXmlInstruction.Locations.after
							)
						);
				s.Add(doc, new AddXmlInstruction(
							@"<add key=""middle"" value=""2"" />",
							"//settings/add[@key='last']",
							AddXmlInstruction.Locations.before
							)
						);
				
				s.Update(doc, new UpdateXmlInstruction("//settings/add[@key='middle']", "changed"));

				s.Delete(doc, new DeleteXmlInstruction("//settings/add[@key='first']"));

				Assert.AreEqual(@"<?xml version=""1.0"" encoding=""utf-8""?><configuration><settings><add key=""middle"" value=""2"">changed</add><add key=""last"" value=""3"" /></settings></configuration>", doc.OuterXml);
			}
			catch (Exception x)
			{
				var m = x.Message;
			}
		}

		[TestMethod]
		public void Test_AddProperty()
		{
			try
			{
				var xmlService = new XmlService();
				var s = new InstructionService(xmlService);
				var pl = new List<Property>();

				s.Add(pl, new AddPropertyInstruction("key1","val1"));
				Assert.AreEqual(1, pl.Count);

				s.Add(pl, new AddPropertyInstruction("key2", "val2"));
				Assert.AreEqual(2, pl.Count);
			}
			catch (Exception x)
			{
				var m = x.Message;
			}
		}

		[TestMethod]
		public void Test_UpdateProperty()
		{
			try
			{
				var xmlService = new XmlService();
				var s = new InstructionService(xmlService);
				var pl = new List<Property>();

				s.Add(pl, new AddPropertyInstruction("key1", "val1"));
				Assert.AreEqual(1, pl.Count);

				s.Update(pl, new UpdatePropertyInstruction("key1", "val2"));
				Assert.AreEqual(1, pl.Count);
				Assert.AreEqual("val2", pl.FirstOrDefault(p => p.key == "key1").value);
			}
			catch (Exception x)
			{
				var m = x.Message;
			}
		}

		[TestMethod]
		public void Test_DeleteProperty()
		{
			try
			{
				var xmlService = new XmlService();
				var s = new InstructionService(xmlService);
				var pl = new List<Property>();

				s.Add(pl, new AddPropertyInstruction("key1", "val1"));
				Assert.AreEqual(1, pl.Count);

				s.Add(pl, new AddPropertyInstruction("key2", "val2"));
				Assert.AreEqual(2, pl.Count);

				s.Delete(pl, new DeletePropertyInstruction("key1"));
				Assert.AreEqual(1, pl.Count);
				Assert.AreEqual("val2", pl[0].value);

			}
			catch (Exception x)
			{
				var m = x.Message;
			}
		}
	}
}
